﻿using HDSmartCommunity.BUS;
using HDSmartCommunity.DevicePlatform;
using HDSmartCommunity.Models;
using Microsoft.VisualStudio.Web.CodeGeneration.Contracts.Messaging;
using OfficeOpenXml;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace HDSmartCommunity.Tool
{
    public abstract class AbstractCOMDevice : AbstractDevices
    {
        private Socket client;
        private Thread thread;

        public override bool ConnectServer(string serverIP, int port)
        {
            try
            {
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                client.Connect(serverIP, port);
                //server.ReceiveTimeout = 10000;
                thread = new Thread(StartReceive);
                thread.Start(client);
                int index = KoneVoltageSerialData.kone_list.FindIndex(x => x.DeviceIP == serverIP && x.DevicePort == port);
                if (index > -1)
                {
                    KoneDeviceInfo koneDeviceinfo = KoneVoltageSerialData.kone_list[index];
                    koneDeviceinfo.ConnectFlag = true;
                    koneDeviceinfo.socket = client;
                    KoneVoltageSerialData.kone_list[index] = koneDeviceinfo;
                }
                return true;
            }
            catch (Exception e)
            {
                LogHelper.Log("连接恒大异常" + e.ToString());
                return false;
            }
        }

        //接收消息
        public void StartReceive(object obj)
        {
            byte[] buffer = new byte[2048];
            int length = 0;
            while (true)
            {
                try
                {
                    length = client.Receive(buffer);
                    if (length == 0)
                    {
                        break;
                    }
                    else
                    {
                        IPEndPoint remoteEP = client.RemoteEndPoint as IPEndPoint;
                        string deviceip = remoteEP.Address.ToString();
                        int port = remoteEP.Port;
                        //LogHelper.Log(deviceip + ":" + port + "," + Untils.ToHexs(buffer.Skip(0).Take(length).ToArray()));
                        int device_index = KoneVoltageSerialData.kone_list.FindIndex(x => x.DeviceIP == deviceip && x.DevicePort == port);
                        if (device_index > -1)
                        {
                            KoneDeviceInfo koneDeviceInfo = KoneVoltageSerialData.kone_list[device_index];
                            for (int i = 0; i < length; i++)
                            {
                                //判断电池充电、逆变状态
                                if (buffer[i] == 0x01 && buffer[i + 1] == 0x03 && buffer[i + 2] == 0x0C)
                                {

                                    int numcount = 12;
                                    byte[] buffers = new byte[numcount + 3];
                                    for (int j = 0; j < buffers.Length; j++)
                                    {
                                        buffers[j] = buffer[i + j];
                                    }
                                    byte[] crc = Crc18(buffers);
                                    if (crc[0] == buffer[i + 16] && crc[1] == buffer[i + 15])
                                    {
                                        byte[] nb_statu_byte = new byte[] { buffers[i + 4], buffers[i + 3], 0x00, 0x00 };
                                        int nb_status = BitConverter.ToInt32(nb_statu_byte);//逆变状态
                                        byte[] cd_statu_byte = new byte[] { buffers[i + 14], buffers[i + 13], 0x00, 0x00 };
                                        int cd_status = BitConverter.ToInt32(cd_statu_byte);//充电状态

                                        int ChargeStatus = 0;//充电状态
                                        int DisChargeStatus = 0;//逆变状态
                                        int BatteryStatus = 0;//电池充电逆变状态
                                        if (nb_status == 3)
                                        {
                                            DisChargeStatus = 1;
                                        }
                                        else if (nb_status == 4)
                                        {
                                            DisChargeStatus = 2;
                                        }
                                        if (cd_status == 1)
                                        {
                                            ChargeStatus = 1;
                                        }
                                        else if (cd_status == 2)
                                        {
                                            ChargeStatus = 1;
                                        }
                                        else if (cd_status == 3)
                                        {
                                            ChargeStatus = 3;
                                        }

                                        if (DisChargeStatus == 1)
                                        {
                                            BatteryStatus = 2;
                                        }
                                        else if (ChargeStatus == 1)
                                        {
                                            BatteryStatus = 1;
                                        }

                                        int index = KoneVoltageSerialData.deviceStatuses.FindIndex(x => x.DeviceIP == deviceip && x.DevicePort == port);
                                        if (index > -1)
                                        {
                                            DeviceStatus deviceStatus = KoneVoltageSerialData.deviceStatuses[index];
                                            if (deviceStatus.ChargeStatus != ChargeStatus)
                                            {
                                                if (ChargeStatus == 1)
                                                {
                                                    deviceStatus.ChargeStartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                                }
                                                deviceStatus.ChargeStatus = ChargeStatus;
                                            }
                                            if (deviceStatus.DisChargeStatus != DisChargeStatus)
                                            {
                                                if (DisChargeStatus == 1)
                                                {
                                                    deviceStatus.DisChargeStartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                                }
                                                deviceStatus.DisChargeStatus = DisChargeStatus;
                                            }
                                            if (deviceStatus.BatteryStatus != BatteryStatus)
                                            {
                                                deviceStatus.BatteryStatus = BatteryStatus;
                                            }
                                            KoneVoltageSerialData.deviceStatuses[index] = deviceStatus;
                                        }
                                        else
                                        {
                                            DeviceStatus deviceStatus = new DeviceStatus();
                                            deviceStatus.DeviceName = koneDeviceInfo.DeviceName;
                                            deviceStatus.DevicePort = koneDeviceInfo.DevicePort;
                                            deviceStatus.DeviceIP = koneDeviceInfo.DeviceIP;
                                            deviceStatus.DisChargeStatus = DisChargeStatus;
                                            deviceStatus.ChargeStatus = ChargeStatus;
                                            deviceStatus.BatteryStatus = BatteryStatus;
                                            if (DisChargeStatus == 1)
                                            {
                                                deviceStatus.DisChargeStartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                            }
                                            if (ChargeStatus == 1)
                                            {
                                                deviceStatus.ChargeStartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                            }
                                            KoneVoltageSerialData.deviceStatuses.Add(deviceStatus);
                                        }
                                    }
                                }
                                //记录充电、逆变时电压数据
                                else if (buffer[i] == 0x01 && buffer[i + 1] == 0x03 && buffer[i + 2] == 0x26)
                                {
                                    int numcount = 38;
                                    byte[] buffers = new byte[numcount + 3];
                                    for (int j = 0; j < buffers.Length; j++)
                                    {
                                        buffers[j] = buffer[i + j];
                                    }
                                    byte[] crc = Crc18(buffers);
                                    if (crc[0] == buffer[i + 42] && crc[1] == buffer[i + 41])
                                    {
                                        byte[] nb_voltage_byte = new byte[] { buffers[i + 4], buffers[i + 3], 0x00, 0x00 };
                                        int nb_voltage = BitConverter.ToInt32(nb_voltage_byte, 0);//逆变电压
                                        byte[] cd_voltage_byte = new byte[] { buffers[i + 22], buffers[i + 21], buffers[i + 20], buffers[i + 19] };
                                        int cd_voltage = BitConverter.ToInt32(cd_voltage_byte); //充电电压
                                        byte[] nb_falut_byte = new byte[] { buffers[i + 32], buffers[i + 31], 0x00, 0x00 };
                                        int nb_falut = BitConverter.ToInt32(nb_falut_byte);//逆变过程中的故障
                                        byte[] cd_falut_byte = new byte[] { buffers[i + 34], buffers[i + 33], 0x00, 0x00 };
                                        int cd_fault = BitConverter.ToInt32(cd_falut_byte);//充电时电池故障
                                        byte[] nb_statu_byte = new byte[] { buffers[i + 30], buffers[i + 29], 0x00, 0x00 };
                                        int nb_status = BitConverter.ToInt32(nb_statu_byte);//逆变状态
                                        byte[] cd_statu_byte = new byte[] { buffers[i + 40], buffers[i + 39], 0x00, 0x00 };
                                        int cd_status = BitConverter.ToInt32(cd_statu_byte);//充电状态
                                        int ChargeStatus = 0;
                                        int DisChargeStatus = 0;
                                        if (nb_status == 3)
                                        {
                                            DisChargeStatus = 1;
                                        }
                                        else if (nb_status == 0x04)
                                        {
                                            DisChargeStatus = 2;
                                        }

                                        if (cd_status == 1)
                                        {
                                            ChargeStatus = 1;
                                        }
                                        else if (cd_status == 2)
                                        {
                                            ChargeStatus = 2;
                                        }
                                        else if (cd_status == 3)
                                        {
                                            ChargeStatus = 3;
                                        }
                                        string type = "";

                                        if (DisChargeStatus == 1)
                                        {
                                            type = "DisCharge";
                                        }
                                        else
                                        {
                                            type = "Charge";
                                        }

                                        int index = KoneVoltageSerialData.deviceStatuses.FindIndex(x => x.DeviceIP == deviceip && x.DevicePort == port);
                                        if (index > -1)
                                        {
                                            DeviceStatus deviceStatus = KoneVoltageSerialData.deviceStatuses[index];
                                            if (deviceStatus.ChargeStatus != ChargeStatus)
                                            {
                                                if (ChargeStatus == 1)//开始充电
                                                {
                                                    deviceStatus.ChargeStartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                                    deviceStatus.ChargeStopTime = "";
                                                }
                                                else if (ChargeStatus == 3)//停止充电
                                                {
                                                    deviceStatus.ChargeStopTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                                }

                                                if (DisChargeStatus == 1)//开始逆变
                                                {
                                                    deviceStatus.DisChargeStartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                                    deviceStatus.DisChargeStopTime = "";
                                                }
                                                else if (DisChargeStatus == 2)//停止逆变
                                                {
                                                    deviceStatus.DisChargeStopTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                                }
                                            }

                                            string starttime = "";
                                            string stoptime = "";
                                            if (type == "DisCharge")
                                            {
                                                stoptime = deviceStatus.DisChargeStopTime;
                                                starttime = deviceStatus.DisChargeStartTime;
                                            }
                                            else
                                            {
                                                stoptime = deviceStatus.ChargeStopTime;
                                                starttime = deviceStatus.ChargeStartTime;
                                            }
                                            InsertExcelData(nb_voltage, cd_voltage, nb_falut, cd_fault, deviceStatus.DeviceName, starttime, stoptime, type);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    continue;
                }
            }
        }

        public bool InsertExcelData(int nb_voltage, int cd_voltage, int nb_falut, int cd_fault, string devicename, string starttime, string endtime, string type)
        {
            try
            {
                string path = AppDomain.CurrentDomain.BaseDirectory;
                string dirpath = string.Empty;
                if (type == "Charge")
                {
                    dirpath = AppDomain.CurrentDomain.BaseDirectory + @"wwwroot/TestData/Charge/" + devicename;
                }
                else
                {
                    dirpath = AppDomain.CurrentDomain.BaseDirectory + @"wwwroot/TestData/DisCharge/" + devicename;
                }
                string filepath = dirpath + @"/" + devicename + "_" + DateTime.Now.ToString("yyyy-MM-dd") + ".csv";
                //LogHelper.Log(filepath);
                //生成目录
                //创建文件夹
                if (Directory.Exists(dirpath) == false)//如果不存在就创建file文件夹
                {
                    Directory.CreateDirectory(dirpath);
                }

                // 判断文件是否存在，不存在则创建，否则读取值显示到txt文档
                if (!System.IO.File.Exists(filepath))
                {
                    FileStream fs1 = new FileStream(filepath, FileMode.Create, FileAccess.Write);//创建写入文件 

                    fs1.Close();
                    if (type == "Charge")
                    {
                        File.AppendAllText(filepath, "Id,ItemType,ChargeCount,ChargeStartTime,ChargeStopTime,BatteryVoltage,DischargeVoltage,FaultCode,CreateDateTime" + "\r\n");
                        File.AppendAllText(filepath, string.Format("1,{0},{1},{2},{3},{4},{5},{6},{7}", devicename, 1, starttime, endtime, Math.Round(cd_voltage * 0.001, 3), Math.Round(nb_voltage * 1.727, 2), cd_fault, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) + "\r\n");
                    }
                    else
                    {
                        File.AppendAllText(filepath, "Id,ItemType,DisChargeCount,DisChargeStartTime,DisChargeStopTime,BatteryVoltage,DischargeVoltage,FaultCode,CreateDateTime" + "\r\n");
                        File.AppendAllTextAsync(filepath, string.Format("1,{0},{1},{2},{3},{4},{5},{6},{7}", devicename, 1, starttime, endtime, Math.Round(cd_voltage * 0.001, 3), Math.Round(nb_voltage * 1.727, 2), nb_falut, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) + "\r\n");
                    }
                }
                else
                {
                    if (type == "Charge")
                    {
                        File.AppendAllTextAsync(filepath, string.Format("1,{0},{1},{2},{3},{4},{5},{6},{7}", devicename, 1, starttime, endtime, Math.Round(cd_voltage * 0.001, 3), Math.Round(nb_voltage * 1.727, 2), cd_fault, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) + "\r\n");
                    }
                    else
                    {
                        File.AppendAllTextAsync(filepath, string.Format("1,{0},{1},{2},{3},{4},{5},{6},{7}", devicename, 1, starttime, endtime, Math.Round(cd_voltage * 0.001, 3), Math.Round(nb_voltage * 1.727, 2), nb_falut, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) + "\r\n");
                    }
                }
            }
            catch (Exception ex)
            {
                DataSaveLogHelper.Log(ex.ToString());
            }
            return true;
        }

        #region CRC校验
        public byte[] Crc18(byte[] buffer, int start = 0, int len = 0)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0xFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            Array.Reverse(ret);
            return ret;
        }
        #endregion
    }
}
